package fr.ing4.Macri.MonteCarlo.GUI;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Hashtable;
import java.util.Observable;
import java.util.Observer;
import java.util.Scanner;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

/**
 * 
 * @author antoinerichard
 *GUI class 
 */

public class MyFrame extends JFrame implements Observer {

	/**
	 * 
	 */
	int multi=1; //1 mode multithread 0 single thread
	static final int HEIGHT= 600;
	static final int WIDTH=1100;
	private static final long serialVersionUID = 1L;
	public int launchCustom=1;
	
	public fr.ing4.Macri.MonteCarlo.SingleThread.MonteCarloSimulation calculator;
	public fr.ing4.Macri.MonteCarlo.MultiThread.MonteCarloSimulation multilator;

	
	private Container bigPanel;
	private JPanel titlePanel, centerPanel, bottomPanel;
	private JLabel titleLbl;
	public JLabel premiumRes;
	private JLabel timeRes;
	private JPanel tablePanel;
	private JPanel slidersPanel;
	private DefaultTableModel tableModel;
	private JTable table;
	private JScrollPane pane;
	private JLabel stockSlLbl;
	private JLabel strikeSlLbl;
	private JLabel DiscountSlLbl;
	private JLabel maturitySlLbl;
	private JLabel carrySlLbl;
	private JLabel volaSlLbl;
	private JButton goButton;
	public JSlider modeSl,StkPriceSl,StrikePriceSl,DiscountSl,maturitySl,carrySl,volaSl,nStepsSl,nSimuSl, chunkSl;
	public JButton singleModeBtn;
	public JButton multiModeBtn;
	public JButton switchBtn;
	
	
	
	
	public MyFrame()
	{   
		//Call superclass constructor
		super("Macri-Richard_Advanced Java");
		
		
		
		
		
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(new Dimension(WIDTH, HEIGHT));
		this.setLocationRelativeTo(null);
		
		
		
		
		bigPanel = this.getContentPane();
		bigPanel.setLayout(new GridLayout(1,2));
		
		singleModeBtn =new JButton("SingleThread");
		multiModeBtn =new JButton("MultiThread");
		singleModeBtn.addActionListener(new TheListener(this));
		multiModeBtn.addActionListener(new TheListener(this));
		singleModeBtn.setFont(new Font("Serif", Font.PLAIN, 30));
		multiModeBtn.setFont(new Font("Serif", Font.PLAIN, 30));
		
		bigPanel.add(this.singleModeBtn);
		bigPanel.add(this.multiModeBtn);
		this.setVisible(true);
	}
		
	public void buildGUI()
	{
		
		if(this.multi==0)
		{
		this.calculator=new fr.ing4.Macri.MonteCarlo.SingleThread.MonteCarloSimulation(this);
	    this.calculator.addObserver(this);
		}
	else{
	this.multilator= new fr.ing4.Macri.MonteCarlo.MultiThread.MonteCarloSimulation(this);
	this.multilator.addObserver(this);
	}
		
		bigPanel.removeAll();
	    bigPanel=this.getContentPane();
	    setBigPanel();
	    setTitlePanel();
	    setCenterPanel();
	    setBottomPanel();
		
	    
	    this.setListeners();
	    this.setVisible(true);
	    
	    
		
		
	}
	
	
	private void setBigPanel()
	{
		bigPanel.setLayout(new BorderLayout());
		titlePanel=new JPanel();
		centerPanel=new JPanel();
		bottomPanel=new JPanel();
		
		bigPanel.add(titlePanel,BorderLayout.PAGE_START);
		bigPanel.add(centerPanel,BorderLayout.CENTER);
		bigPanel.add(bottomPanel,BorderLayout.PAGE_END);
	}
	
	
	private void setTitlePanel()
	{
		titlePanel.setLayout(new BorderLayout());
		titlePanel.setBackground(new Color(241,241,241));
		
		titleLbl=new JLabel("Monte Carlo");
		titleLbl.setHorizontalAlignment(JLabel.CENTER);
		titleLbl.setFont(new Font("Serif", Font.PLAIN, 30));
		titlePanel.add(titleLbl, BorderLayout.CENTER);
		
		if(this.multi==0)switchBtn = new JButton("Switch to Multithread mode");
		if(this.multi==1)switchBtn = new JButton("Switch to Singlethread mode");
		switchBtn.setHorizontalAlignment(JLabel.CENTER);
		JPanel tempPanel=new JPanel();
		tempPanel.add(switchBtn);
		titlePanel.add(tempPanel,BorderLayout.SOUTH);
		
		
		
	}
	
	private void setCenterPanel()
	{
		centerPanel.setLayout(new GridLayout(1,2));
		tablePanel=new JPanel();
		slidersPanel=new JPanel();
		setTablePanel();
		setSlidersPanel();
		
		centerPanel.add(tablePanel);
		centerPanel.add(slidersPanel);
		
	}
	
	private void setBottomPanel()
	{
		bottomPanel.setLayout(new GridLayout(3,1));
		titlePanel.setBackground(Color.WHITE);
		
		JLabel resultsLbl = new JLabel("Results");
		resultsLbl.setFont(new Font("Serif", Font.PLAIN, 25));
		resultsLbl.setHorizontalAlignment(JLabel.CENTER);
		premiumRes=new JLabel("Premium : ");
		premiumRes.setHorizontalAlignment(JLabel.CENTER);
		timeRes=new JLabel("Time : ");
		timeRes.setHorizontalAlignment(JLabel.CENTER);
		
		
		bottomPanel.add(resultsLbl);
		bottomPanel.add(premiumRes);
		bottomPanel.add(timeRes);
	}
	
	private void setTablePanel()
	{
		tablePanel.setBackground(new Color(241,241,241));
		tablePanel.setLayout(new BorderLayout());
		String[] entetes = {"Flag","Stock Price", "Strike Price", "Discount Rate", "Maturity","Carry Rate", "Volatility","nSteps","nSimulations"};
	    Object[][] donnees={{}};
	    tableModel = new DefaultTableModel(donnees, entetes);
	    this.loadPresets();
	     
	    table=new JTable(tableModel);
	    pane=new JScrollPane(table);
	    
	    JLabel presetsLbl = new JLabel("Presets");
	    presetsLbl.setFont(new Font("Serif", Font.PLAIN, 25));
	    presetsLbl.setHorizontalAlignment(JLabel.CENTER);
	    
	    goButton = new JButton("Launch!");
	    goButton.setFont(new Font("Serif", Font.PLAIN, 25));
	    
	    tablePanel.add(presetsLbl,BorderLayout.PAGE_START);
	    tablePanel.add(pane,BorderLayout.CENTER);
	    tablePanel.add(goButton, BorderLayout.PAGE_END);
	}
	
	private void setSlidersPanel()
	{
		slidersPanel.setBackground(new Color(241,241,241));
		slidersPanel.setLayout(new GridLayout(10,2));
		
		modeSl = createSlider(0,2) ;
		//Create the label table
		Hashtable<Integer, JLabel> labelTable = new Hashtable<Integer, JLabel>();
		labelTable.put( new Integer( 0 ), new JLabel("Call") );
		labelTable.put( new Integer( 2 ), new JLabel("Put") );
		modeSl.setLabelTable( labelTable );
		JLabel modeSlLbl = new JLabel("Mode");
		//stockSlLbl.setVerticalAlignment(JLabel.BOTTOM);
		modeSlLbl.setHorizontalAlignment(JLabel.CENTER);
		slidersPanel.add(modeSlLbl);
		slidersPanel.add(modeSl);    
		
		StkPriceSl = createSlider(0,1000) ;
		stockSlLbl=new JLabel("Stock Price");
		//stockSlLbl.setVerticalAlignment(JLabel.BOTTOM);
		stockSlLbl.setHorizontalAlignment(JLabel.CENTER);
		slidersPanel.add(stockSlLbl);
		slidersPanel.add(StkPriceSl);
		
		StrikePriceSl = createSlider(0,1000);
		strikeSlLbl=new JLabel("Strike Price");
		//strikeSlLbl.setVerticalAlignment(JLabel.BOTTOM);
		strikeSlLbl.setHorizontalAlignment(JLabel.CENTER);
		slidersPanel.add(strikeSlLbl);
		slidersPanel.add(StrikePriceSl);
		
		DiscountSl = createSlider(0,100);
		DiscountSlLbl=new JLabel("Discount Rate (%)");
		//strikeSlLbl.setVerticalAlignment(JLabel.BOTTOM);
		DiscountSlLbl.setHorizontalAlignment(JLabel.CENTER);
		slidersPanel.add(DiscountSlLbl);
		slidersPanel.add(DiscountSl);
		
		maturitySl = createSlider(0,36);
		maturitySlLbl=new JLabel("Time to maturity (months)");
		//strikeSlLbl.setVerticalAlignment(JLabel.BOTTOM);
		maturitySlLbl.setHorizontalAlignment(JLabel.CENTER);
		slidersPanel.add(maturitySlLbl);
		slidersPanel.add(maturitySl);
		
		carrySl = createSlider(0,100);
		carrySlLbl=new JLabel("Cost of carry rate (%)");
		//strikeSlLbl.setVerticalAlignment(JLabel.BOTTOM);
		carrySlLbl.setHorizontalAlignment(JLabel.CENTER);
		slidersPanel.add(carrySlLbl);
		slidersPanel.add(carrySl);
		
		volaSl = createSlider(0,100);
		volaSlLbl=new JLabel("Volatility (%)");
		//strikeSlLbl.setVerticalAlignment(JLabel.BOTTOM);
		volaSlLbl.setHorizontalAlignment(JLabel.CENTER);
		slidersPanel.add(volaSlLbl);
		slidersPanel.add(volaSl);
		
		nStepsSl = createSlider(0,332);
		JLabel nStepsSlLbl = new JLabel("nSteps");
		//strikeSlLbl.setVerticalAlignment(JLabel.BOTTOM);
		nStepsSlLbl.setHorizontalAlignment(JLabel.CENTER);
		slidersPanel.add(nStepsSlLbl);
		slidersPanel.add(nStepsSl);
		
		nSimuSl = createSlider(0,1000000);
		JLabel nSimuSlLbl = new JLabel("nSimulations");
		//strikeSlLbl.setVerticalAlignment(JLabel.BOTTOM);
		nSimuSlLbl.setHorizontalAlignment(JLabel.CENTER);
		slidersPanel.add(nSimuSlLbl);
		slidersPanel.add(nSimuSl);
		
		chunkSl = createSlider(1,100000);
		JLabel chunkSlLbl = new JLabel("Data Chunk");
		chunkSlLbl.setHorizontalAlignment(JLabel.CENTER);
		chunkSl.setValue(Runtime.getRuntime().availableProcessors());
		if(this.multi==1)
			{
			slidersPanel.add(chunkSlLbl);
			slidersPanel.add(chunkSl);
			}
		
	}
	
	
	private JSlider createSlider(int min, int max)
	{
		JSlider temp = new JSlider(JSlider.HORIZONTAL,min, max, (min+max)/2);
		//Turn on labels at major tick marks.
		temp.setMajorTickSpacing(max/4);
		temp.setMinorTickSpacing(max/40);
		temp.setPaintTicks(true);
		temp.setPaintLabels(true);
		
		return temp;
	}
	
	private void loadPresets()
	{
		Scanner inputStream;
		File fichier = new File("Resources/Presets.csv");
		tableModel.setRowCount(0);
		
		try {
			inputStream = new Scanner(fichier);
			while (inputStream.hasNext()) {
			// read single line, put in string
			String data = inputStream.nextLine();
			// Split de la ligne
			String dataTab[] = data.split(";");
			tableModel.addRow(dataTab);
		}
			String data="Custom";
			String dataTab[] = data.split(";");
			tableModel.addRow(dataTab);
		inputStream.close();
		} catch (FileNotFoundException e) {
			
			e.printStackTrace();
		}
		
		
			
			
			
		
	}
	
	private void setListeners()
	{
		this.goButton.addActionListener(new TheListener(this));
		this.table.getSelectionModel().addListSelectionListener(new TheListener(this));
		this.modeSl.addChangeListener(new TheListener(this));
		this.StkPriceSl.addChangeListener(new TheListener(this));
		this.StrikePriceSl.addChangeListener(new TheListener(this));
		this.DiscountSl.addChangeListener(new TheListener(this));
		this.maturitySl.addChangeListener(new TheListener(this));
		this.carrySl.addChangeListener(new TheListener(this));
		this.volaSl.addChangeListener(new TheListener(this));
		this.nStepsSl.addChangeListener(new TheListener(this));
		this.nSimuSl.addChangeListener(new TheListener(this));
		this.chunkSl.addChangeListener(new TheListener(this));
		this.switchBtn.addActionListener(new TheListener(this));
	}


	/**
	 * @return the goButton
	 */
	public JButton getGoButton() {
		return goButton;
	}


	/**
	 * @return the table
	 */
	public JTable getTable() {
		return table;
	}
	
	@Override
	public void update(Observable o, Object arg) {
		if(this.multi==0) {
			fr.ing4.Macri.MonteCarlo.SingleThread.MonteCarloSimulation notifier=(fr.ing4.Macri.MonteCarlo.SingleThread.MonteCarloSimulation) arg;
			
			if(notifier.isFinish()){
			this.premiumRes.setText("Premium : "+String.valueOf(notifier.getRes()));
			this.timeRes.setText("Time : "+String.valueOf(notifier.getTime()));
			}
			else{ this.timeRes.setText("Progress : "+notifier.progress+"%");}
		}
		else {
			fr.ing4.Macri.MonteCarlo.MultiThread.MonteCarloSimulation notifier=(fr.ing4.Macri.MonteCarlo.MultiThread.MonteCarloSimulation) arg;
			
			if(notifier.isFinish())
			{
			this.premiumRes.setText("Premium : "+String.valueOf(notifier.getRes()));
			this.timeRes.setText("Time : "+String.valueOf(notifier.getTime()));
			}
			else
			{
			this.timeRes.setText("Progress : "+notifier.progress+"%");
			}
			}
		
		
		this.goButton.setEnabled(true);
		this.goButton.setText("Re-Launch?");
		
	}

	
	public static void main(String[] args) {
	
	  @SuppressWarnings("unused")
	MyFrame Cadre=new MyFrame();
      
	}

}
